package yxk.task;

import kd.bos.context.RequestContext;
import kd.bos.dataentity.entity.DynamicObject;
import kd.bos.dataentity.entity.DynamicObjectCollection;
import kd.bos.exception.KDException;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import kd.bos.orm.query.QCP;
import kd.bos.orm.query.QFilter;
import kd.bos.schedule.executor.AbstractTask;
import kd.bos.servicehelper.BusinessDataServiceHelper;
import kd.bos.servicehelper.operation.DeleteServiceHelper;
import kd.bos.servicehelper.operation.SaveServiceHelper;
import kd.sdk.plugin.Plugin;
import yxk.utils.DateUtil;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 考勤项目取值表任务插件
 */
public class AttProjectValueTask extends AbstractTask implements Plugin {
    private static final Log log = LogFactory.getLog(AttProjectValueTask.class);
    private SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
    SimpleDateFormat hms=new SimpleDateFormat("HH:mm");
    @Override
    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {

        Map<String, Map<String, String>> conn = getDynamicList();
        List<List<DynamicObject>> dyList=new ArrayList<>();
        List<DynamicObject>  dys=new ArrayList<>();
        int i=0;
        for (String key : conn.keySet()) {
            DynamicObject single = BusinessDataServiceHelper.newDynamicObject("nwg5_attprojectvalue");
            Map<String, String> maps = conn.get(key);
            single.set("personid",Long.parseLong(maps.get("personid"))); //考勤人
            try {
                Date parse = format.parse(maps.get("owndate"));
                single.set("owndate", parse);     //归属日期[;[pl=-po
                single.set("time",String.valueOf(parse.getTime()));     //时间毫秒
            }catch (Exception e){
                log.info("归属日期转换失败");
            }
            single.set("results",maps.get("result"));                    //考勤结果
            single.set("origin",maps.get("origin"));                     //原始出勤时长
            single.set("reality",maps.get("reality"));                   //实际出勤时长
            single.set("classes",maps.get("classes"));                   //班次
            single.set("effectives",maps.get("effective"));              //有效卡点
            single.set("frees",maps.get("free"));                       //原始卡点
            single.set("shift",maps.get("shift"));                      //班次文本
            single.set("attmain",maps.get("attmain"));                  //主表
            single.set("persondate",key);                               //用于判断唯一
            dys.add(single);
            if(dys.size() == 200000 || i== conn.size()-1){
                dyList.add(dys);
                dys = new ArrayList<>();
            }
           i++;
        }
        for (List<DynamicObject> list : dyList) {
            SaveServiceHelper.save(list.toArray(new DynamicObject[list.size()]));
        }


    }

    public Map<String,Map<String,String>> getDynamicList(){
        String formatted = format.format(new Date());
        try {
            Date parse = format.parse(formatted);
            QFilter qFilter=new QFilter("calculatedate", QCP.large_equals,parse);
            DynamicObject[] loaded = BusinessDataServiceHelper.load("wtdtd_attrecordbase", "id,personid,dateattr,shiftid,owndate", qFilter.toArray());
            //考勤人员明细ID
            Map<String,Map<String, String>> baseMap=new HashMap<>();
            List<Set<Long>> setList=new ArrayList<>();
            Set<Long> ids=new HashSet<>();
            Set<Long> personIds=new HashSet<>();
            Set<Long> shiftids=new HashSet<>();
            //同步结束时间
            Date starDate=parse;
            //主表信息
            for (int i = 0; i < loaded.length; i++) {
                DynamicObject single=loaded[i];
                String id = single.getString("id");
                DynamicObject shiftid = single.getDynamicObject("shiftid");
                Date owndate = single.getDate("owndate");
                if(starDate.getTime() > owndate.getTime()){
                    starDate=owndate;
                }
                DynamicObject personid = single.getDynamicObject("personid");
                String person = personid.getPkValue().toString();
                String number = personid.getString("number");
                String dateStr = format.format(owndate);
                StringBuffer key=new StringBuffer(person);
                key.append(dateStr);
                Map<String, String> personMap = baseMap.get(key.toString());
                if(personMap == null){
                    personMap=new HashMap<>();
                }
                String tid = shiftid.getPkValue().toString();
                personMap.put("attmain",id);//主表ID
                personMap.put("classes",tid); //班次ID
                personMap.put("owndate",dateStr);   //归属日期
                personMap.put("personid",person);   //计算人员ID
                personMap.put("number",number);     //计算人员编码
                baseMap.put(key.toString(),personMap);
                //班次ID
                shiftids.add(Long.parseLong(tid));
                //主表ID
                ids.add(Long.parseLong(id));
                if(ids.size() == 100000 || i == loaded.length-1){
                    setList.add(ids);
                    ids=new HashSet<>();
                }
                //人员ID集合
                personIds.add(Long.parseLong(person));
            }
            //考勤项目集合
            Map<String, Map<String, Map<String, String>>> attRecordDetails = this.getAttRecordDetails( setList);
            log.info("AttProjectValueTask.execute.attRecordDetails.size:{}",attRecordDetails.size());
            //原始卡点
            Map<String, List<Date>> signCards = this.getSignCards(personIds, starDate, parse);
            log.info("AttProjectValueTask.execute.signCards.size:{}",signCards.size());
            //有效卡点
            Map<String, Map<String, String>> multiCards = this.getMultiCards(personIds, starDate, parse);
            log.info("AttProjectValueTask.execute.multiCards.size:{}",multiCards.size());
            List<String> keyList=new ArrayList<>();
            Map<String,Map<String,String>> conn=new HashMap<>();
            for (String key : baseMap.keySet()) {
                Map<String,String> mapAtt = new HashMap<>();
                //获取人员主表信息
                Map<String, String> attMap = baseMap.get(key);
                String person = attMap.get("personid");
                String owndate = attMap.get("owndate");
                String classes = attMap.get("classes");
                String attmain = attMap.get("attmain");
                //原始卡点时间集合
                List<Date> signDates = signCards.get(key);
                if(signDates != null && signDates.size() > 0) {
                    String free = this.getDateString(signDates);
                    mapAtt.put("free",free); //原始卡点
                }
                //获取有效卡点集合
                Map<String, String> effMap = multiCards.get(key);
                if(effMap != null ) {
                    String multiDates = effMap.get("eff");
                    mapAtt.put("effective", multiDates);      //有效卡点
                    String shift = effMap.get("shift");
                    mapAtt.put("shift", shift);          //班次文本
                }
                //考勤项目集合
                Map<String, Map<String, String>> recordMap = attRecordDetails.get(key);
                String origin="";//原始出勤时长
                String reality="";//实际出勤时长
                StringBuffer result=new StringBuffer(); //考勤结果  异常项目
                StringBuffer result1=new StringBuffer();//考勤结果  休假、出差时长
                StringBuffer result2=new StringBuffer();//考勤结果  展示加班时长
                for (String row : recordMap.keySet()) {
                    Map<String, String> attRecord = recordMap.get(row);
                    String name = attRecord.get("name");
                    String unit = attRecord.get("unit");
                    String value = attRecord.get("value");
                    switch (row){
                        case "AT_1040":
                            reality=value;
                            break;
                        case "AT_1020":
                            origin=value;
                            break;
                        case "EX_1010_S":
                        case "EX_1020_S":
                        case "1001":
                        case "1002":
                        case "RE_1030_S":
                        case "EX_1140_S":
                            if(!"0.00".equals(value)){
                                result.append(name);
                                result.append(value);
                                result.append(unit);
                                result.append(";");
                            }
                            break;
                        case "LE_1180_S":
                        case "LE_1200_S":
                        case "LE_1170_S":
                        case "LE_1190_S":
                        case "LE_1210_S":
                        case "LE_1220_S":
                        case "LE_1230_S":
                        case "LE_1240_S":
                        case "LE_1270_S":
                        case "1005":
                        case "1008":
                        case "1011":
                        case "1017":
                        case "1020":
                        case "1023":
                        case "BT_1020_S":
                        case "BT_1040_S":
                            if(!"0.00".equals(value)){
                                result1.append(name);
                                result1.append(value);
                                result1.append(unit);
                                result1.append(";");
                            }
                            break;
                        case"OT1_1100_S":
                        case"OT1_1130_S":
                        case"OT2_1110_S":
                        case"OT2_1140_S":
                        case"OT3_1120_S":
                        case"OT3_1150_S":
                            if(!"0.00".equals(value)){
                                result2.append(name);
                                result2.append(value);
                                result2.append(unit);
                                result2.append(";");
                            }
                            break;
                    }

                }
                if( result == null || "".equals(result.toString())){
                    result.append("正常;");
                }
                result.append(result1);
                result.append(result2);
                mapAtt.put("personid",person);          //考勤人
                mapAtt.put("owndate",owndate);          //归属日期
                mapAtt.put("attmain",attmain);          //主表
                mapAtt.put("classes",classes);          //班次ID

                mapAtt.put("origin",origin);            //原始出勤时长
                mapAtt.put("reality",reality);          //实际出勤时长
                mapAtt.put("result",result.toString()); //考勤结果
                mapAtt.put("key",key);                  //用于判断唯一
                log.info("AttProjectValueTask.execute.mapAtt:{}",mapAtt);
                conn.put(key,mapAtt);
                keyList.add(key);
            }
            QFilter keyQf=new QFilter("persondate", QCP.in,keyList);

            DeleteServiceHelper.delete("nwg5_attprojectvalue",keyQf.toArray());
            return conn;
        } catch (Exception e) {
            log.error("AttProjectValueTask.execute.e:{}",e);
            throw new RuntimeException();
        }
    }

    private String getDateString(List<Date> dates){
        StringBuffer str=new StringBuffer();
        Collections.sort(dates, new Comparator<Date>() {
            @Override
            public int compare(Date date1, Date date2) {
                return date1.compareTo(date2);
            }
        });
        for (int i = 0; i < dates.size(); i++) {
            Date date = dates.get(i);
            String attDate = hms.format(date);
            str.append(attDate);
            if(i != dates.size()-1){
                str.append(",");
            }

        }
        return str.toString();
    }

    /**
     * 考勤项目
     * @param ids  主表ID集合
     * @return
     */
    private Map<String,Map<String, Map<String, String>>> getAttRecordDetails(List<Set<Long>> ids){
        Map<String,Map<String, Map<String, String>>> maps=new HashMap<>();
        for (Set<Long> id : ids) {
            QFilter qF=new QFilter("attmain", QCP.in,id);
            DynamicObject[] loads = BusinessDataServiceHelper.load("wtdtd_attrecorddetail", "attmain,attitemid,valuestring", qF.toArray());
            for (DynamicObject row : loads) {
                //获取考勤明细数据
                DynamicObject att = row.getDynamicObject("attmain");
                String person = att.getString("personid.id");
                Date owndate = att.getDate("owndate");
                String own = format.format(owndate);
                StringBuffer key=new StringBuffer(person);
                key.append(own);
                //根据人员
                Map<String, Map<String, String>> personMap = maps.get(key.toString());
                if(personMap == null){
                    personMap = new HashMap<>();
                }
                //获取考勤项目
                DynamicObject attitemid = row.getDynamicObject("attitemid");

                Map<String,String> map=new HashMap<>();
                //项目编码
                String number = attitemid.getString("number");
                //项目名称
                String name = attitemid.getString("name");
                //项目单位
                String unitNumber = attitemid.getString("unit");
                String unit="";
                switch (unitNumber){
                    case "day":
                        unit="天";
                        break;
                    case "hour":
                        unit="小时";
                        break;
                    case "minute":
                        unit="分钟";
                        break;
                    case "second":
                        unit="秒";
                        break;
                    case "time":
                        unit="次";
                        break;

                }
                //考勤项目核算值
                String value = row.getString("valuestring");
                map.put("name",name);
                map.put("unit",unit);
                map.put("value",value);
                personMap.put(number,map);
                maps.put(key.toString(),personMap);
            }
        }
        return maps;
    }

    /**
     * 获取原始卡点
     * @param personIds     人员ID集合
     * @param starDate      班次开始时间
     * @param endDate       班次结束时间
     * @return
     */
    private Map<String,List<Date>> getSignCards(Set<Long> personIds,Date starDate,Date endDate){
        QFilter cardQF=new QFilter("attperson", QCP.in,personIds)
                .and("signpoint", QCP.large_equals,starDate)
                .and("signpoint",QCP.less_equals, DateUtil.getEndTime(endDate))
                .and("status", QCP.equals,"1");
        DynamicObject[] signcards = BusinessDataServiceHelper.load("wtpd_signcard", "signpoint,attperson", cardQF.toArray());
        Map<String,List<Date>> cardMap=new HashMap<>();
        for (DynamicObject card : signcards) {
            DynamicObject attperson = card.getDynamicObject("attperson");
            String person = attperson.getPkValue().toString();
            //打卡时间
            Date signpoint = card.getDate("signpoint");
            String sign = format.format(signpoint);
            //人员ID和时间作为唯一ID
            StringBuffer key=new StringBuffer(person);
            key.append(sign);
            List<Date> personList = cardMap.get(key.toString());
            if(personList == null){
                personList=new ArrayList<>();
            }
            personList.add(signpoint);
            cardMap.put(key.toString(),personList);
        }
        log.info("AttProjectValueTask.getSignCards.cardMap:{}",cardMap);
        return cardMap;
    }



    /**
     * 获取有效卡点
     * @param personIds     人员ID集合
     * @param starDate      班次开始时间
     * @param endDate       班次结束时间
     * @return
     */
    private Map<String,Map<String,String>> getMultiCards(Set<Long> personIds,Date starDate,Date endDate){
        Map<String,Map<String,String>> map=new HashMap<>();
        QFilter multiQF=new QFilter("attperson", QCP.in,personIds)
                .and("shiftdate", QCP.large_equals,starDate)
                .and("shiftdate",QCP.less_equals, DateUtil.getEndTime(endDate));
        String multiTxt="attperson,shift,entryentity,effectivepoint,shiftdate,mustpoint";
        DynamicObject[] multiCards = BusinessDataServiceHelper.load("wtpm_multicard", multiTxt, multiQF.toArray());
        log.info("AttProjectValueTask.getMultiCards.multiCards:{}",multiCards);
        for (DynamicObject row : multiCards) {
            DynamicObject attperson = row.getDynamicObject("attperson");
            String person = attperson.getPkValue().toString();
            Date shiftdate = row.getDate("shiftdate");
            String attDate = format.format(shiftdate);
            StringBuffer key=new StringBuffer(person);
            key.append(attDate);
            StringBuffer effective=new StringBuffer();
            //获取班次
            DynamicObject shift = row.getDynamicObject("shift");
            StringBuffer shiftBuff=new StringBuffer();
            shiftBuff.append(shift.getString("number"));
            shiftBuff.append("|");
            shiftBuff.append(shift.getString("name"));
            shiftBuff.append(":");
            DynamicObjectCollection collection = row.getDynamicObjectCollection("entryentity");
            for (DynamicObject ent : collection) {
                //获取有效卡点
                Date eff = ent.getDate("effectivepoint");
                if(eff != null) {
                    String formatted = hms.format(eff);
                    effective.append(formatted);
                }else{
                    effective.append("-");
                }
                effective.append(",");
                //获取应打卡点
                Date mustpoint = ent.getDate("mustpoint");
                if(mustpoint != null){
                    String ted = hms.format(mustpoint);
                    shiftBuff.append(ted);
                    shiftBuff.append(",");
                }
            }
            String eff = effective.toString();
            String substring = eff.substring(0, eff.length() - 1);
            String buff = shiftBuff.toString();
            String shiftSub = buff.substring(0, buff.length() - 1);
            Map effMap=new HashMap<>();
            effMap.put("eff",substring);
            effMap.put("shift",shiftSub);
            map.put(key.toString(),effMap);
        }
        log.info("AttProjectValueTask.getMultiCards.map:{}",map);
        log.info("AttProjectValueTask.getMultiCards.mapSize:{}",map.size());
        return map;

    }

}